home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.08 Aug 91 / ListHandler Code / TrueDemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-29  |  12.9 KB  |  565 lines  |  [TEXT/KAHL]

  1. /*                                            ListDemo.c                                            */
  2. /*
  3.  *
  4.  * Demo my homemade LDEF.  The program lets you open
  5.  * a file and display all of the icons in it.  You
  6.  * can't do anything else, though it would be easy
  7.  * to allow you to copy an icon to the clipboard.
  8.  *
  9.  * Copyright 1990 Martin Minow and MacTutor.
  10.  */
  11. #include "iconicLDEF.h"
  12.  
  13. #define FORMAT    TRUE_RESOURCE                /* Define  program    */
  14. /*
  15.  * These values configure the demo program: that way
  16.  * we only need to write one piece of code.
  17.  */
  18. #define COMPILED            0
  19. #define    FAKE_RESOURCE    1
  20. #define    TRUE_RESOURCE    2
  21. #if FORMAT == FAKE_RESOURCE || FORMAT == TRUE_RESOURCE
  22. #define LDEF_ID                128
  23. #else
  24. #define LDEF_ID                0                    /* Start with Mac LDEF    */
  25. #endif
  26. #define RESOURCE            'ICN#'
  27. #define iconSize            32                /* Pixels per icon            */
  28. #define sBarWidth            15                /* For grow button            */
  29. #define iconCols             4
  30. #define iconRows             4
  31. #define    hOffsetDelta    16                /* For multiple windows    */
  32. #define vOffsetDelta    0
  33. #define hOffsetMax    (hOffsetDelta * 10)
  34. #define vOffsetMax    (vOffsetDelta * 10)
  35.  
  36. /*
  37.  * Menu organization
  38.  */
  39. enum Menus {
  40.     MENU_Apple            = 1,
  41.     MENU_File                = 256,
  42.     MENU_Edit                = 257
  43. };
  44.  
  45. enum Apple_Menu {
  46.     Apple_About = 1
  47. };
  48.  
  49. enum File_Menu {
  50.     File_Open        = 1,
  51.     File_Close,
  52.     File_DrawAsText,
  53.     File_Debug,
  54.     Unused,
  55.   File_Quit
  56. };
  57.  
  58. #define width(r)        ((r).right - (r).left)
  59. #define height(r)        ((r).bottom - (r).top)
  60.  
  61. /*
  62.  * All the information about a document
  63.  * is stored here.  Note that, when the
  64.  * toolbox selects a window, we can
  65.  * immediately recover the document.
  66.  */
  67. typedef struct {
  68.     WindowRecord    window;
  69.     ListHandle        list;
  70. } DocumentRecord, *DocumentPtr;
  71. /*
  72.  * The current window is always stored in a local
  73.  * WindowPtr variable named "window."  If it's ours,
  74.  * we can access the document by casting window to
  75.  * DocumentPtr and de-referencing it.
  76.  */
  77. #define DOC            (*((DocumentPtr) window))
  78.  
  79. /*
  80.  * isOurWindow is TRUE if its argument is our document.
  81.  */
  82. #define isOurWindow(window)    (                                                        \
  83.             (window) != NIL                                                                        \
  84.         && ((WindowPeek) (window))->windowKind == userKind    \
  85.      )
  86.  
  87. MenuHandle            apple_menu;
  88. MenuHandle            file_menu;
  89. Boolean                    drawAsText;                /* For iconicLDEF()     */
  90. int                            hOffset, vOffset;
  91.  
  92. void                        main(void);
  93. Boolean                    do_mouse(EventRecord);
  94. Boolean                    handle_events(void);
  95. void                        do_command(long);
  96. void                        setup(void);
  97. void                        open_document(void);
  98. void                        close_document(WindowPtr);
  99. Boolean                    new_document(void *, int);
  100. Boolean                    initialize_list(WindowPtr);
  101. void                        read_icons(WindowPtr, int);
  102.  
  103. #if FORMAT == FAKE_RESOURCE
  104. void                        setup_LDEF(int);
  105. #endif
  106. #if FORMAT == COMPILED
  107. void                        add_LDEF(ListHandle);
  108. void                        remove_LDEF(ListHandle);
  109. #endif
  110. void                        iconicLDEF();
  111.  
  112. /*
  113.  * main()
  114.  * Initialize the program and run the event loop.
  115.  */
  116. void
  117. main()
  118. {
  119.         EventRecord            event;
  120.         WindowPtr                window;
  121.         GrafPtr                    save_port;
  122.         Rect                        box;
  123.  
  124.         setup();
  125.         for (;;) {
  126.             SystemTask();
  127.             while (GetNextEvent(everyEvent, &event)
  128.                  && event.what != nullEvent) {
  129.                 if (event.what == activateEvt
  130.                  || event.what == updateEvt)
  131.                      window = (WindowPtr) event.message;
  132.                 else {
  133.                     window = FrontWindow();
  134.                 }
  135.                 switch (event.what) {
  136.                 case mouseDown:
  137.                     do_mouse(event);
  138.                     break;
  139.                 case activateEvt:
  140.                     if (isOurWindow(window)) {
  141.                         SetPort(window);    /* Or InvalRect crashes!    */
  142.                         LActivate(
  143.                              event.modifiers & activeFlag,
  144.                              DOC.list
  145.                         );
  146.                         /*
  147.                          * For some reason, LActivate doesn't redraw
  148.                          * the scroll bars.  The correct solution
  149.                          * is left as a puzzle for the reader.
  150.                          */
  151.                         if (event.modifiers & activeFlag) {
  152.                             ControlHandle    handle;
  153.                             Rect                    box;
  154.                             
  155.                             handle = (**DOC.list).vScroll;
  156.                             if (handle != NIL) {
  157.                                 box = (**handle).contrlRect;
  158.                                 InvalRect(&box);
  159.                             }
  160.                         }
  161.                     } 
  162.                     break;
  163.                 case updateEvt:
  164.                     if (isOurWindow(window)) {
  165.                         GetPort(&save_port);
  166.                         SetPort(window);
  167.                         BeginUpdate(window);
  168.                         EraseRect(&window->portRect);
  169.                         box = (**DOC.list).rView;
  170.                         InsetRect(&box, -1, -1);
  171.                         FrameRect(&box);
  172.                         LDoDraw(TRUE, DOC.list);
  173.                         LUpdate(window->visRgn, DOC.list);
  174.                         EndUpdate(window);
  175.                         SetPort(save_port);
  176.                     }
  177.                     break;
  178.                 default:
  179.                     break;
  180.                 }
  181.             }
  182.         }
  183. }
  184.  
  185. /*
  186.  * do_mouse(event)
  187.  * Process a mouse button press, calling handlers as
  188.  * needed.
  189.  */
  190. static Boolean
  191. do_mouse(event)
  192. EventRecord        event;
  193. {
  194.         WindowPtr            window;
  195.         register int    which_part;
  196.         Rect                    box;
  197.         int                        item;
  198.         Point                    mouse;
  199.         int                        result;
  200.         long                    new, choice;
  201.         Str255                name;
  202.         GrafPtr                save_port;
  203.         
  204.         which_part = FindWindow(event.where, &window);
  205.         switch (which_part) {
  206.         case inDesk:
  207.             SysBeep(2);
  208.             break;
  209.         case inMenuBar:
  210.             choice = MenuSelect(event.where);
  211.             item = LoWord(choice);
  212.             switch (HiWord(choice)) {
  213.             case MENU_Apple:
  214.                 GetItem(apple_menu, item, &name);
  215.                 if (item == Apple_About)
  216.                     SysBeep(10);                /* No List About                    */
  217.                 else {
  218.                     GetPort(&save_port);
  219.                     OpenDeskAcc(name);
  220.                     SetPort(save_port);
  221.                 }
  222.                 break;
  223.             case MENU_File:
  224.                 window = FrontWindow();
  225.                 switch (item) {
  226.                 case File_Open:
  227.                     open_document();
  228.                     break;
  229.                 case File_Close:
  230.                     close_document(window);
  231.                     break;
  232.                 case File_Debug:
  233.                     Debugger();
  234.                     break;
  235.                 case File_DrawAsText:
  236.                     drawAsText = !drawAsText;
  237.                     CheckItem(file_menu, File_DrawAsText, drawAsText);
  238.                     if (isOurWindow(window))
  239.                         InvalRect(&(*window).portRect);
  240.                     break;
  241.                 case File_Quit:
  242.                     ExitToShell();
  243.                 }
  244.                 default:
  245.                     break;
  246.             }
  247.             HiliteMenu(0);
  248.             break;
  249.         case inDrag:
  250.             box = screenBits.bounds;
  251.             box.top += GetMBarHeight();
  252.             InsetRect(&box, 4, 4);
  253.             DragWindow(window, event.where, &box);
  254.             break;
  255.         case inContent:
  256.             if (FrontWindow() != window)
  257.                 SelectWindow(window);
  258.             else {
  259.                 SetPort(window);
  260.                 if (isOurWindow(window)) {
  261.                     mouse = event.where;
  262.                     GlobalToLocal(&mouse);
  263.                     result = LClick(mouse, event.modifiers, DOC.list);
  264.                     (void) LLastClick(DOC.list);
  265.                 }
  266.             }
  267.             break;
  268.         case inGoAway:
  269.             if (isOurWindow(window)
  270.              && TrackGoAway(window, event.where))
  271.                     close_document(window);
  272.             break;
  273.         }
  274.         return (FALSE);
  275. }
  276.  
  277. /*
  278.  * open_document()
  279.  * Ask for a file (allow all files).  Open its resource
  280.  * fork (if possible).  If we succeed, create a new
  281.  * window and look for all ICN# resources.
  282.  */ 
  283. void
  284. open_document()
  285. {
  286.         SFReply                    reply;
  287.         int                            file;
  288.         static Point        where = { 85, 85 };
  289.  
  290.         SFGetFile(
  291.             where,                                    /* Where on the screen        */
  292.             NIL,                                        /* Unused                                    */
  293.             NIL,                                        /* no file filter                    */
  294.             -1,                                            /* Allow all file types        */
  295.             NIL,                                        /* … thus no typeList            */
  296.             NIL,                                        /* no dialog hook                    */
  297.             &reply                                    /* reply goes here                */
  298.         );
  299.         if (reply.good) {
  300.             SetVol(NIL, reply.vRefNum);
  301.             SetCursor(*GetCursor(watchCursor));
  302.             if ((file = OpenResFile(reply.fName)) == -1)
  303.                 SysBeep(10);                    /* No resource fork                */
  304.             else {
  305.                 if (new_document(reply.fName, file) == FALSE)
  306.                     SysBeep(10);                /* No memory                            */
  307.                 CloseResFile(file);
  308.             }
  309.             SetCursor(&arrow);
  310.         }
  311. }
  312.  
  313. /*
  314.  * close_document()
  315.  * Close the document in the current (front) window.
  316.  * Dump the handles that were stored in the list's cells.
  317.  */
  318. void
  319. close_document(window)
  320. WindowPtr            window;
  321. {
  322.         IconInfo        iconInfo;
  323.         short                size;
  324.         Cell                cell;
  325.  
  326.         if (isOurWindow(window) == FALSE)
  327.             Debugger();
  328.         SetCursor(*GetCursor(watchCursor));
  329.         /*
  330.          * Iterate over all cells in the list.
  331.          */
  332.         cell.h = cell.v = 0;
  333.         do {
  334.             size = sizeof iconInfo;
  335.             LGetCell(&iconInfo, &size, cell, DOC.list);
  336.             if (size == sizeof iconInfo)    /* Non-empty cell?    */
  337.                 DisposHandle(iconInfo.handle);
  338.         } while (LNextCell(TRUE, TRUE, &cell, DOC.list));
  339. #if FORMAT == COMPILED
  340.         remove_LDEF(DOC.list);
  341. #endif
  342.         LDispose(DOC.list);
  343.         CloseWindow(window);
  344.         DisposPtr(window);
  345.         SetCursor(&arrow);
  346. }
  347.  
  348. /*
  349.  * setup()
  350.  * One-time initialization.
  351.  */
  352. void
  353. setup()
  354. {
  355.         InitGraf(&thePort);
  356.         InitFonts();
  357.         FlushEvents(everyEvent, 0);
  358.         InitWindows();
  359.         InitMenus();
  360.         TEInit();
  361.         InitDialogs(NIL);
  362.         InitCursor();
  363.         MaxApplZone();
  364.         apple_menu = NewMenu(MENU_Apple, "\p\024");
  365.         file_menu = NewMenu(MENU_File, "\pFile");
  366.         AppendMenu(apple_menu, "\p(No List Demo About;(-");
  367.         AddResMenu(apple_menu, 'DRVR');
  368.         AppendMenu(
  369.             file_menu,
  370.             "\pOpen\311/O;Close;Draw As Text;Debug/.;(-;Quit/Q"
  371.         );
  372.         InsertMenu(apple_menu, 0);
  373.         InsertMenu(file_menu, 0);
  374.         DrawMenuBar();
  375. #if FORMAT == FAKE_RESOURCE
  376.         setup_LDEF(LDEF_ID);
  377. #endif
  378.         if (new_document("\pList Demo", -1) == FALSE) {
  379.             SysBeep(10);
  380.             ExitToShell();
  381.         }
  382. }
  383.  
  384. /*
  385.  * new_document()
  386.  * Build a document: get memory for the WindowRecord and
  387.  * our attached information.  Offset the window with
  388.  * respect to other windows and make the window.  If
  389.  * this succeeds, initialize the document's list.  If
  390.  * that succeeds, read the icons.
  391.  */
  392. Boolean
  393. new_document(title, resFile)
  394. void            *title;                    /* Pascal string                            */
  395. int                resFile;                /* Open resource file, if any    */
  396. {
  397.         WindowPtr            window;
  398.         DocumentPtr        doc;
  399.         Rect                    box;
  400.         static long        sequence;        /* Identify windows                */
  401.         
  402.         doc = (DocumentPtr) NewPtr(sizeof (DocumentRecord));
  403.         if (doc == NIL)
  404.             return (FALSE);
  405.         /*
  406.          * Locate the window and get its shape.  This could
  407.          * probably be done better.
  408.          */
  409.         box.left = 0;
  410.         box.top = GetMBarHeight() * 2;
  411.         box.right = box.left
  412.                             + (iconSize * iconCols)
  413.                             + sBarWidth
  414.                             + 2;
  415.         box.bottom = box.top
  416.                             + (iconSize * iconRows)
  417.                             + 2;
  418.         OffsetRect(&box, hOffset, vOffset); 
  419.         if (box.bottom > screenBits.bounds.bottom
  420.          || box.right > screenBits.bounds.right) {
  421.              OffsetRect(&box, -hOffset, -vOffset);
  422.              hOffset = 0;
  423.              vOffset = 0;
  424.         }
  425.         hOffset += hOffsetDelta;
  426.         if (hOffset >= hOffsetMax)
  427.             hOffset = 0;
  428.         vOffset += vOffsetDelta;
  429.         if (vOffset >= vOffsetMax)
  430.             vOffset = 0;
  431.         window = NewWindow(
  432.                     doc,                                /* Allocated storage            */
  433.                     &box,                                /* Display Rect                        */
  434.                     title,                            /* Title                                    */
  435.                     TRUE,                                /* Visible on creation        */
  436.                     noGrowDocProc,            /* Window type                        */
  437.                     -1L,                                /* Show in front                    */
  438.                     TRUE,                                /* GoAway box                            */
  439.                     ++sequence                    /* RefCon    (debug only)        */
  440.                 );
  441.         if (window == NIL) {
  442.             DisposPtr(doc);
  443.             return (FALSE);
  444.         }
  445.         if (initialize_list(window) == FALSE) {
  446.             CloseWindow(window);
  447.             DisposPtr(doc);
  448.             return (FALSE);
  449.         }
  450.         SetPort(window);
  451.         TextFont(applFont);
  452.         TextSize(9);
  453.         read_icons(window, resFile);
  454.         return (TRUE);
  455. }
  456.  
  457. /*
  458.  * initialize_list()
  459.  * Build a list whose cells will hold our icon records.
  460.  * If our LDEF is completely compiled, call add_LDEF
  461.  * after creation.
  462.  */
  463. Boolean
  464. initialize_list(window)
  465. WindowPtr            window;
  466. {
  467.         int                    type;
  468.         Handle            handle;
  469.         int                    *jump;
  470.         Rect                box;
  471.         Point                cell;
  472.         Rect                dimension;
  473.         
  474.         box = (*window).portRect;
  475.         InsetRect(&box, 1, 1);            /* Room for frame                */
  476.         box.right -= sBarWidth;
  477.         SetPt(&cell, iconSize, iconSize);
  478.         box.bottom =
  479.             box.top + (height(box) / cell.v) * cell.v;
  480.         box.right =
  481.             box.left + (width(box) / cell.h) * cell.h;
  482.         SetRect(&dimension, 0, 0, box.right / cell.h, 0);
  483.         DOC.list = LNew(
  484.             &box,                                        /* Display rectangle            */
  485.             &dimension,                            /* Shape (rows, cols)            */
  486.             cell,                                        /* Cell shape on screen        */
  487.             LDEF_ID,                                /* List handler, if any        */
  488.             window,                                    /* The window                            */
  489.             TRUE,                                        /* Drawing's ok                        */
  490.             FALSE,                                    /* No grow box                        */
  491.             FALSE,                                    /* No horizontal scroll        */
  492.             TRUE                                        /* Vertical scroll                */
  493.         );
  494.         if (DOC.list == NIL)
  495.             return (FALSE);
  496.         (**DOC.list).selFlags = lOnlyOne;
  497. #if FORMAT == COMPILED
  498.         add_LDEF(DOC.list);
  499. #endif
  500.         (**DOC.list).refCon = (long) iconicLDEF;
  501.         return (TRUE);
  502. }
  503.  
  504. /*
  505.  * read_icons()
  506.  * Fill the list with the icon handles and resource ids.
  507.  */
  508. void
  509. read_icons(window, resFile)
  510. WindowPtr                window;
  511. int                            resFile;
  512. {
  513.         int                    n_icons;
  514.         int                    i;
  515.         int                    n_rows, n_cols;
  516.         Cell                cell;
  517.         ResType            type;
  518.         IconInfo        iconInfo;
  519.         Str255            name;
  520.         
  521.         LDoDraw(FALSE, DOC.list);
  522.         if (resFile != -1) {
  523.             UseResFile(resFile);
  524.             n_icons = Count1Resources(RESOURCE);
  525.         }
  526.         else {
  527.             n_icons = CountResources(RESOURCE);
  528.         }
  529.         n_cols = (**DOC.list).dataBounds.right;
  530.         n_rows = (n_icons + (n_cols - 1)) / n_cols;
  531.         /*
  532.          * Note that we can have empty cells in the last row.
  533.          * The drawing routine must check for this case.
  534.          */
  535.         if (n_rows > 0)
  536.             LAddRow(n_rows, 0, DOC.list);
  537.         for (i = 0; i < n_icons; i++) {
  538.             if (resFile != -1)
  539.                 iconInfo.handle = Get1IndResource(RESOURCE, i + 1);
  540.             else {
  541.                 iconInfo.handle = GetIndResource(RESOURCE, i + 1);
  542.             }
  543.             if (iconInfo.handle == NIL)
  544.                 iconInfo.number = -1;
  545.             else {
  546.                 GetResInfo(
  547.                     iconInfo.handle, &iconInfo.number, &type, name);        
  548.                 DetachResource(iconInfo.handle);
  549.             }
  550.             cell.v = i / n_cols;
  551.             cell.h = i % n_cols;
  552.             LSetCell(&iconInfo, sizeof iconInfo, cell, DOC.list);
  553. #if 0        /* Debug: watch the icons as they're read in        */
  554.             {
  555.                 Rect            rect;
  556.                 SetRect(&rect, 1, 1, 33, 33);
  557.                 PlotIcon(&rect, iconInfo.handle);
  558.             }
  559. #endif
  560.         }
  561.         LDoDraw(TRUE, DOC.list);
  562.         InvalRect(&(**DOC.list).rView);
  563. }
  564.  
  565.